package com.gin.kotlin.no_gay_alliance.fragment.replylist

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import com.gin.kotlin.no_gay_alliance.activity.PostActivity.PostResult
import com.gin.kotlin.no_gay_alliance.activity.ReplyListActivity
import com.gin.kotlin.no_gay_alliance.app.App
import com.gin.kotlin.no_gay_alliance.argument.PostPrepareArgument.Action
import com.gin.kotlin.no_gay_alliance.argument.ReplyListArgument
import com.gin.kotlin.no_gay_alliance.base.AbstractBindingFragment
import com.gin.kotlin.no_gay_alliance.callback.RCallback
import com.gin.kotlin.no_gay_alliance.database.entity.TopicHistory
import com.gin.kotlin.no_gay_alliance.databinding.FragmentReplyPageAbstractBinding
import com.gin.kotlin.no_gay_alliance.enums.HandlerMessageWhat
import com.gin.kotlin.no_gay_alliance.provider.ngaphp.ReplyListProvider
import com.gin.nga.callback.NgaCallback
import com.gin.nga.response.base.NgaResponse
import com.gin.nga.response.post.PrepareBody
import com.gin.nga.response.reply.CustomReputationLevel
import com.gin.nga.response.reply.ReplyInfo
import com.gin.nga.response.reply.ReplyListBody
import com.gin.nga.response.topic.TopicDetail
import retrofit2.Call
import retrofit2.Response

/**
 * 一页回复，渲染组件留空
 * @property levels 自定义声望等级
 * @property topic 主题信息
 * @property launcher 启动器
 * @property argument 参数
 * @property forumId 版面ID
 * @property forumName 版面名称
 * @property historyRecordAble 是否可以记录主题历史
 */
abstract class AbstractReplyPageFragment : AbstractBindingFragment<FragmentReplyPageAbstractBinding>(), RCallback<ReplyListBody, ReplyListArgument>,
    ActivityResultCallback<ActivityResult> {
    var levels: List<CustomReputationLevel>? = null
    var topic: TopicDetail? = null
    lateinit var launcher: ActivityResultLauncher<Intent>
    lateinit var argument: ReplyListArgument
    protected var forumId: Long? = null
    protected var forumName: String? = null
    private var historyRecordAble = false

    /**
     * 请求成功，执行渲染
     * @param replies MutableList<ReplyInfo>?
     */
    abstract fun onSuccess(replies: MutableList<ReplyInfo>?)

    /**
     * 请求错误时的回调，如清空或隐藏渲染组件
     */
    abstract fun onError()

    /**
     * 滚动到指定楼层
     * @param floorNumber Int
     */
    abstract fun scrollToFloor(floorNumber: Int)

    /**
     * 滚动到指定回复ID的楼层
     * @param replyId Int
     */
    abstract fun scrollToReply(replyId: Long)

    /**
     * 初始化渲染组件
     */
    abstract fun initRenderComponent(b: FragmentReplyPageAbstractBinding)

    override fun onResume() {
        super.onResume()
        (requireActivity() as? ReplyListActivity)?.onFragmentVisible(this)

        // 发送消息更新当前页
        findParentHandler().sendMessage(HandlerMessageWhat.PAGE_UPDATED, this.argument.page!!)
    }

    override fun onPause() {
        super.onPause()
        // 离开页面时，更新历史中的当前页
        if (historyRecordAble) App.INSTANCE.database.topicHistoryDao().updatePage(this.argument.topicId!!, this.argument.page!!)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d(TAG, "onDestroyView: 销毁渲染组件")
    }

    /**
     * 刷新
     */
    open fun refresh() {
        request(true)
        Log.i(TAG, "刷新")
    }

    /**
     * onCreateView的后续操作 ，如通过  [FragmentActivity.addMenuProvider] 添加菜单
     */
    final override fun onCreateView() {
        val b = this.b ?: return
        b.tvWarning.visibility = View.GONE
        b.swipeRefreshLayout.setOnRefreshListener { refresh() }
        this.launcher = registerLauncher(this)
        //初始化渲染组件
        initRenderComponent(b)
        // 发送请求
        request()
    }

    /**
     * 解析错误时执行
     */
    final override fun onFailed(ignoreCache: Boolean, params: ReplyListArgument?) {
        val p = params?.copy(html = true)
        Log.i(TAG, "使用HTML模式请求: ${mapper.writeValueAsString(p)}")
        ReplyListProvider.getInstance().enqueue(p, ignoreCache = ignoreCache, callback = this)
    }

    final override fun onError(errorMessage: String) {
        Log.w(TAG, "请求错误")
        val b = this.b ?: return
        ui {
            b.tvWarning.visibility = View.VISIBLE
            b.swipeRefreshLayout.isRefreshing = false
            // 报错信息
            b.tvWarning.text = errorMessage
        }
        // 清空数据
        onError()
    }

    /**
     * 处理参数
     * @param bundle Bundle
     */
    final override fun handleArguments(bundle: Bundle) {
        this.argument = parseBundle(bundle, ReplyListActivity.KEY_ARGUMENT, ReplyListArgument::class.java)

        //是否可以记录主题历史：为LIST模式，且不是只看某人
        this.historyRecordAble = this.argument.type == ReplyListArgument.Type.LIST && this.argument.userId == null
    }

    final override fun onSuccess(data: ReplyListBody, ignoreCache: Boolean) {
        (requireActivity() as? ReplyListActivity)?.also { activity ->
            if (argument.type == ReplyListArgument.Type.HISTORY) {
                activity.setToolbarTitle("编辑历史")
            } else
                data.topic?.title?.also { activity.setToolbarTitle(it) }
        }
        val b = this.b ?: return
        this.levels = data.forum?.levels
        this.topic = data.topic
        this.forumId = data.topic?.forumId
        this.forumName = data.forum?.forumName

        Log.i(TAG, "打开主题: ${data.topic?.title} - ${data.topic?.type}: ${data.topic?.getStatus()}")

        // 关闭动画
        ui {
            b.swipeRefreshLayout.isRefreshing = false
        }
        Log.i(TAG, "请求成功: ${mapper.writeValueAsString(this.argument)}")

        // 更新当前页信息
        data.totalPage?.also {
            findParentHandler().sendMessage(HandlerMessageWhat.PAGE_UPDATED, 0, it)
        }
        // 更新总楼层数
        data.total?.also {
            findParentHandler().sendMessage(HandlerMessageWhat.TOTAL_UPDATED, it, 0)
        }

        // 记录主题历史
        if (historyRecordAble) App.INSTANCE.database.topicHistoryDao().add(TopicHistory(data))

        val replies = data.replies?.toMutableList()

        //  仅当当前非倒序楼时，填充缺失楼层占位
        if (data.topic?.isReversed() != true) {
            // 当前页
            val cPage = data.page
            // 总页数
            val tPage = data.totalPage ?: this.argument.totalPage
            // 最大楼层号, 外面传入的或当前获得的中的最大值总回复数 -1  ，否则使用 (总页数-1)*20
            val maxFloorNumber = listOfNotNull(data.total, this.argument.total).maxOrNull()?.minus(1) ?: tPage?.minus(1)?.times(20)

            if (maxFloorNumber != null) {
                // 当前页最小楼层号
                val min = (cPage - 1) * 20
                // 当前页最大楼层号
                val max = maxFloorNumber.coerceAtMost(min + 19)
                Log.d(TAG, "当前页楼层范围: [$min,$max]")

                // 已有楼层号
                val floorNumbers = replies?.map { it.floorNumber }
                for (i in min until max + 1) {
                    // 如果缺失该楼层号，添加到指定位置
                    if (floorNumbers?.contains(i) == false) {
                        replies.add(i - min, ReplyInfo().also { it.floorNumber = i })
                    }
                }
            }
        }
        // 如果指定了回复id，但该回复未在返回列表中，检查审核状态

        argument.replyId?.also { pid ->
            val ids = data.replies?.mapNotNull { it.replyId }
            if (ids?.contains(pid) == false) {
                Log.i(TAG, "检查审核状态, 目标回复id：${pid}，已有回复id: $ids")
                App.INSTANCE.ngaApi.postApi.prepareReply(data.topic!!.topicId, pid).enqueue(object : NgaCallback<PrepareBody> {
                    override fun onSuccess(
                        call: Call<NgaResponse<PrepareBody>>,
                        response: Response<NgaResponse<PrepareBody>>,
                        body: NgaResponse<PrepareBody>?,
                        data: PrepareBody?
                    ) {
                        Log.w(TAG, "onSuccess: 该回复可见")
                    }

                    override fun onError(
                        call: Call<NgaResponse<PrepareBody>>,
                        response: Response<NgaResponse<PrepareBody>>,
                        body: NgaResponse<PrepareBody>?,
                        errorMessage: String
                    ) {
                        handler?.toastLong(errorMessage)
                    }
                })
            }
        }


        // 执行渲染操作
        onSuccess(replies)
    }

    final override fun onActivityResult(result: ActivityResult) {
        Log.i(TAG, "发帖结果")

        val postResult = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            result.data?.getParcelableExtra(PostResult::class.java.simpleName, PostResult::class.java)
        } else {
            result.data?.getParcelableExtra(PostResult::class.java.simpleName)
        } ?: return

        // 如果是编辑操作，原地刷新，其他操作则抛出到活动处理
        when (postResult.action) {
            Action.MODIFY -> refresh()
            else -> findParentHandler().sendMessage(HandlerMessageWhat.POST_SUCCESS, postResult)
        }
    }

    /**
     *发送请求
     * @param ignoreCache Boolean
     */

    private fun request(ignoreCache: Boolean = false) {
        val b = this.b ?: return
        b.tvWarning.visibility = View.GONE
        b.swipeRefreshLayout.isRefreshing = true
        ReplyListProvider.getInstance().enqueue(this.argument, ignoreCache = ignoreCache, callback = this)
    }


}
